package mq

import (
	log "ac-common-go/glog"
	config "ac-julink/tool/config"
	"encoding/base64"
	"encoding/json"
	"errors"
	"github.com/go-stomp/stomp"
	"strings"
	"time"
)

var MQClientPool *stomp.Pool

// activemq 连接池
func InitMqPool(username, password string, mqSSL int) {
	var connOptions []func(*stomp.Conn) error = []func(*stomp.Conn) error{
		stomp.ConnOpt.Login(username, password),
		//stomp.ConnOpt.Login("guest", "guest"),
		stomp.ConnOpt.Host("/"),
	}
	addr := config.GetConfigValue("WGNS", "wgconfig_server_broker_uri")
	maxIdle, ok := config.GetConfigIntValue("WGNS", "wgconfig_activemq_max_idle")
	if !ok {
		maxIdle = 10000
	}
	maxActive, ok := config.GetConfigIntValue("WGNS", "wgconfig_activemq_max_active")
	if !ok {
		maxActive = 100
	}
	idleTimeout, ok := config.GetConfigIntValue("WGNS", "wgconfig_activemq_idle_timeout")
	if !ok {
		idleTimeout = 240
	}

	MQClientPool = &stomp.Pool{
		MaxIdle:     maxIdle,
		MaxActive:   maxActive,
		IdleTimeout: time.Duration(idleTimeout) * time.Second,
		Dial: func() (*stomp.Conn, error) {
			brokerAddr := strings.Split(addr, "*")
			if len(brokerAddr) == 0 {
				log.Errorf("ActiveMQ dial start error, brokerAddr is empty")
				return nil, errors.New("ActiveMQ dial start error, brokerAddr is empty")
			}
			var c *stomp.Conn
			var err error
			for _, ip := range brokerAddr {
				if mqSSL == 1 {
					c, err = stomp.Dial("tcp", ip, connOptions...)
				} else {
					c, err = Dial("tcp", ip, connOptions...)
				}

				if err == nil {
					log.Infof("current connected activemq addr:%s", ip)
					break
				}
			}
			if err != nil {
				log.Errorf("activemq pool dial err:+v", err)
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c *stomp.Conn, t time.Time) error {
			is_active := c.TestOnBorrow()
			log.Infof("is_active:%+v", is_active)
			if !is_active {
				log.Errorf("TestOnBorrow:this conn has closed,Get next idle connection from the front of idle list")
				return errors.New("this conn has closed,Get next idle connection from the front of idle list")
			}
			return nil
		},
	}
	go MQClientPool.StartIdleConnClearTask() //开启空闲连接清理任务
}

func SendConfigDataResultToService(topic string, _wifiid string, _id int, _seq int, _dataType, _data string, _devid string, _err int) error {

	conn, err := MQClientPool.Get()
	if err != nil {
		log.Errorf("%+v", err)
		return err
	}
	if conn == nil {
		log.Errorf("the conn geted from pool is nil")
		return errors.New("the conn geted from pool is nil")
	}
	defer MQClientPool.Put(conn, false)
	type parseConfigData struct {
		Id       int    `json:"id"`
		WifiId   string `json:"wifiid"`
		Seq      int    `json:"seq"`
		DataType string `json:"dataType"`
		Data     string `json:"data"`
		Devid    string `json:"devid"`
		Err      int    `json:"err"`
	}
	frame := parseConfigData{
		Id:       _id,
		WifiId:   _wifiid,
		Seq:      _seq,
		DataType: _dataType,
		Data:     _data,
		Devid:    _devid,
		Err:      _err,
	}
	frameInBytes, err := json.Marshal(frame)
	if err != nil {
		log.Warning("activemq: Marshal error: ", err.Error())
		return err
	}
	log.Infof("activemq: Send Config result ==> [%s]", string(frameInBytes))
	err = conn.C.Send(topic, "text/json", frameInBytes)
	if err != nil {
		log.Errorf("activemq: failed to send to server err:%+v", err)
		return err
	}
	return nil
}

func SendConfigDataToService(topic, _wifiid string, _id int, _seq int, _dataType, _data, _devid string) error {

	conn, err := MQClientPool.Get()
	if err != nil {
		log.Errorf("%+v", err)
		return err
	}
	if conn == nil {
		log.Errorf("the conn geted from pool is nil")
		return errors.New("the conn geted from pool is nil")
	}
	defer MQClientPool.Put(conn, false)
	type parseConfigData struct {
		Wifiid   string `json:"wifiid"`
		Id       int    `json:"id"`
		Seq      int    `json:"seq"`
		DataType string `json:"dataType"`
		Data     string `json:"data"`
		Devid    string `json:"devid"`
	}
	frame := parseConfigData{
		Wifiid:   _wifiid,
		Id:       _id,
		Seq:      _seq,
		DataType: _dataType,
		Data:     _data,
		Devid:    _devid,
	}
	frameInBytes, err := json.Marshal(frame)
	if err != nil {
		log.Warning("activemq: Marshal error: ", err.Error())
		return err
	}
	log.Infof("activemq: Send Config content ==> [%s]", string(frameInBytes))
	err = conn.C.Send(topic, "text/json", frameInBytes)
	if err != nil {
		log.Errorf("activemq: failed to send to server err:%+v", err)
		return err
	}
	return nil
}

func SendCommonDataResultToService(topic string, _wifiid, _data string, _id int) error {

	conn, err := MQClientPool.Get()
	if err != nil {
		log.Errorf("%+v", err)
		return err
	}
	if conn == nil {
		log.Errorf("the conn geted from pool is nil")
		return errors.New("the conn geted from pool is nil")
	}
	defer MQClientPool.Put(conn, false)
	//对上报data数据base编码
	base64_data := base64.StdEncoding.EncodeToString([]byte(_data))

	type parseConfigData struct {
		Wifiid string `json:"wifiid"`
		Id     int    `json:"msgid"`
		Data   string `json:"data"`
	}
	frame := parseConfigData{
		Wifiid: _wifiid,
		Id:     _id,
		Data:   base64_data,
	}
	frameInBytes, err := json.Marshal(frame)
	if err != nil {
		log.Warning("activemq: Marshal error: ", err.Error())
		return err
	}
	log.Infof("activemq: Send Common content ==> [%s]", string(frameInBytes))

	err = conn.C.Send(topic, "text/plain", frameInBytes)
	if err != nil {
		log.Errorf("activemq: failed to send to server err:%+v", err)
		return err
	}
	return nil
}

// 302升级结果返回给OTA-service
func SendOTAResultToService(topic string, _wifiid, _desc, _wifiversion, _originVersion, _targetVersion string, _err, _resultCode, _policyId int) error {

	conn, err := MQClientPool.Get()
	if err != nil {
		log.Errorf("%+v", err)
		return err
	}
	if conn == nil {
		log.Errorf("the 302 OTA geted from pool is nil")
		return errors.New("the 302 OTA geted from pool is nil")
	}
	defer MQClientPool.Put(conn, false)

	type parseConfigData struct {
		Wifiid          string `json:"wifiId"`
		Err             int    `json:"err"`
		ResultCode      int    `json:"resultCode"`
		Desc            string `json:"desc"`
		PolicyId        int    `json:"policyId"`
		WifiVersion     string `json:"wifiVersion"` // 522 设备目标版本号
		OriginalVersion string `json:"originalVersion"`
		TargetVersion   string `json:"targetVersion"` //酒柜设备目标版本号

	}
	frame := parseConfigData{
		Wifiid:          _wifiid,
		Err:             _err,
		ResultCode:      _resultCode,
		Desc:            _desc,
		PolicyId:        _policyId,
		WifiVersion:     _wifiversion,
		OriginalVersion: _originVersion,
		TargetVersion:   _targetVersion,
	}
	frameInBytes, err := json.Marshal(frame)
	if err != nil {
		log.Warning("activemq: Marshal error: ", err.Error())
		return err
	}
	log.Infof("activemq: Send 302 OTA content ==> [%s]", string(frameInBytes))

	err = conn.C.Send(topic, "text/plain", frameInBytes)
	if err != nil {
		log.Errorf("activemq: failed to send to server err:%+v", err)
		return err
	}
	return nil
}
